# -*- coding: utf-8 -*-

import os
import sys
import time
import wx
import wx.html2
import threading
from ctypes import WinDLL, c_char_p, c_int, create_string_buffer
from tools import get_oa_information_by_idcard, check_result_by_time, print_run, create_csv

# 定义应用程序的一些操作常量
APP_EXIT = 1
APP_COPY_NAME = 2
APP_COPY_ID_CARD_NUM = 3
BUTTON_SEARCH = 4
BUTTON_PRINT = 5

# 初始化一些全局变量
ORIGIN_NAME = ''
ORIGIN_ID_CARD_NUM = ''
INFO_NAME = ''

exit_flag = False

# 定义一个函数来获取资源文件的路径
def resource_path(relative_path):
    """资源文件目录访问路径"""
    if getattr(sys, 'frozen', False):  # 是否Bundle Resource
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

# 定义一个函数来从读卡器获取用户信息
def get_idcard_info(termb):
    """从读卡器获取用户的姓名、身份证号、性别和照片。"""
    termb.GetBmpPhotoExt()
    termb.getName.argtypes = [c_char_p, c_int]
    name = create_string_buffer(64, '\x00')
    termb.getName(name, 64)
    name = name.value.decode('gbk')
    termb.getIDNum.argtypes = [c_char_p, c_int]
    id_num = create_string_buffer(64, '\x00')
    termb.getIDNum(id_num, 64)
    id_num = id_num.value.decode('gbk')
    termb.getIDNum.argtypes = [c_char_p, c_int]
    sex = create_string_buffer(64, '\x00')
    termb.getSex(sex, 64)
    sex = sex.value.decode('gbk')
    image = wx.Bitmap.ConvertToImage(wx.Bitmap('zp.bmp'))
    image = image.Scale(256, 316, wx.IMAGE_QUALITY_HIGH)
    image = wx.Bitmap(image)
    return name, id_num, sex, image

# 定义一个函数来处理读卡器的连接和卡片的读取
def id_card_scan(window):
    """读卡器扫描方法"""
    try:
        # 加载DLL
        termb = WinDLL('./Termb.dll') # 加载读卡器操作的DLL

        # 连接读卡器，InitCommExt会自动搜索串行口1-4和USB接口1001-1004(十进制)，搜索成功返回端口号，否则返回0
        connect_status = termb.InitCommExt()
        if connect_status != 0:
            window.append_log(time.strftime('%Y-%m-%d %H:%M', time.localtime()) + '  ' + '身份证读卡器连接成功', 'green')
            # 轮询检查读卡器状态，如果有卡片在上面则开始读卡
            while not exit_flag:
                card_status = termb.Authenticate()
                if card_status == 1:
                    information_status = termb.ReadContent(2)
                    if information_status == 1:
                        name, id_num, sex, image = get_idcard_info(termb)
                        wx.CallAfter(window.set_label, name, id_num.replace(id_num[:-4], '**************'), image)
                        time.sleep(0.2)

                        oa_result = window.search_oa(sex, id_num)
                        if oa_result:
                            message = create_csv(name, id_num, sex, oa_result)
                            if message:
                                window.append_log(time.strftime('%Y-%m-%d %H:%M', time.localtime()) + '  ' + message,
                                                  'red')
                                image = wx.Bitmap.ConvertToImage(wx.Bitmap('visitor_pic.png'))
                                image = image.Scale(256, 316, wx.IMAGE_QUALITY_HIGH)
                                image = wx.Bitmap(image)

                                time.sleep(4)
                                wx.CallAfter(window.set_label, '', '', image)

                # 文档建议查询间隔时间大于300ms
                time.sleep(0.4)

        else:
            window.append_log(time.strftime('%Y-%m-%d %H:%M', time.localtime()) + '  ' + '身份证读卡器连接失败', 'red')
            dlg = wx.MessageDialog(None, '是否退出程序', '读卡器连接失败', wx.YES_NO | wx.ICON_QUESTION)
            if dlg.ShowModal() == wx.ID_YES:
                window.Destroy()

    except Exception as e:
        window.append_log(time.strftime('%Y-%m-%d %H:%M', time.localtime()) + '  ' + repr(e), 'red')
        dlg = wx.MessageDialog(None, '是否退出程序', '执行文件有误或缺失', wx.YES_NO | wx.ICON_QUESTION)
        if dlg.ShowModal() == wx.ID_YES:
            window.Destroy()

# 定义主窗口类
class MyFrame(wx.Frame):

    def __init__(self):
        style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)
        wx.Frame.__init__(self, None, wx.ID_ANY, '记忆科技访客程序', size=(1200, 720), style=style)
        icon = wx.Icon(resource_path(os.path.join('images', 'icon.ico')), wx.BITMAP_TYPE_ICO)
        self.SetIcon(icon)
        self.len_log = 0

        # 设置菜单栏
        menu_bar = wx.MenuBar()

        common_menu = wx.Menu()
        menu_quit = wx.MenuItem(common_menu, APP_EXIT, '退出')
        common_menu.Append(menu_quit)
        self.Bind(wx.EVT_MENU, self.on_quit, id=APP_EXIT)
        menu_bar.Append(common_menu, '&系统')

        copy_menu = wx.Menu()
        menu_copy_name = wx.MenuItem(copy_menu, APP_COPY_NAME, '复制姓名')
        menu_copy_id_card_num = wx.MenuItem(copy_menu, APP_COPY_ID_CARD_NUM, '复制身份证号')
        copy_menu.Append(menu_copy_name)
        copy_menu.Append(menu_copy_id_card_num)
        self.Bind(wx.EVT_MENU, self.copy_name, id=APP_COPY_NAME)
        self.Bind(wx.EVT_MENU, self.copy_id_card_num, id=APP_COPY_ID_CARD_NUM)
        menu_bar.Append(copy_menu, '&复制')

        self.SetMenuBar(menu_bar)

        # 功能分窗
        self.splitter = wx.SplitterWindow(self)
        self.splitter.SetSashInvisible()
        self.panel_identity = wx.Window(self.splitter, style=wx.BORDER_SUNKEN)
        self.panel_identity.SetBackgroundColour('#FFFFFF')
        self.panel_oa_info = wx.Window(self.splitter, style=wx.BORDER_SUNKEN)
        self.panel_oa_info.SetBackgroundColour('#5F294F')
        self.splitter.SplitVertically(self.panel_identity, self.panel_oa_info, 390)
        pic = wx.Image(resource_path(os.path.join('images', 'visitor_pic.png')),
                       wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        self.visitor_pic = wx.StaticBitmap(parent=self.panel_identity, pos=(65, 120), size=(256, 316),
                                           bitmap=pic, style=wx.BORDER_SIMPLE)
        self.visitor_pic.SetBackgroundColour('#FFFFFF')
        field_font = wx.Font()
        field_font.SetPointSize(16)
        field_font.SetFamily(wx.MODERN)
        field_font.SetWeight(wx.BOLD)
        value_font = wx.Font()
        value_font.SetPointSize(16)
        value_font.SetFamily(wx.MODERN)
        self.name_text = wx.StaticText(self.panel_identity, pos=(76, 480), label='姓名：')
        self.name_text.SetFont(field_font)
        self.name = wx.StaticText(self.panel_identity, pos=(150, 480), label=ORIGIN_NAME)
        self.name.SetFont(value_font)
        self.id_card_num_text = wx.StaticText(self.panel_identity, pos=(30, 520), label='身份证号：')
        self.id_card_num_text.SetFont(field_font)
        self.id_card_num = wx.StaticText(self.panel_identity, pos=(150, 520), label=ORIGIN_ID_CARD_NUM)
        self.id_card_num.SetFont(value_font)
        logo_pic = wx.Image(resource_path(os.path.join('images', 'ramaxel_logo.png')),
                            wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        self.logo_pic = wx.StaticBitmap(parent=self.panel_oa_info, pos=(40, 18), bitmap=logo_pic, style=wx.NO_BORDER)
        welcome_pic = wx.Image(resource_path(os.path.join('images', 'welcome.jpg')),
                               wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        self.welcome_pic = wx.StaticBitmap(parent=self.panel_oa_info, pos=(0, 57), size=(800, 450),
                                           bitmap=welcome_pic, style=wx.NO_BORDER)
        self.FileContent = wx.TextCtrl(parent=self.panel_oa_info, pos=(-3, 507), size=(805, 153),
                                       style=wx.TE_MULTILINE | wx.TE_RICH2)
        font1 = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL, False, 'Consolas')
        self.FileContent.SetFont(font1)

        # 日志打印欢迎标语
        date_now = time.strftime('%Y-%m-%d %H:%M', time.localtime())
        message = f'{date_now}  欢迎使用记忆科技门卫访客程序\n'
        self.append_log(message, 'green')

        # 绑定退出事件
        self.Bind(wx.EVT_CLOSE, self.on_close_window, self)

        # 开启读卡器轮询
        self.t = threading.Thread(target=id_card_scan, args=(self,))
        self.t.start()

    def on_close_window(self, event):
        dlg = wx.MessageDialog(None, '确认退出吗', '确认提示框', wx.YES_NO | wx.ICON_QUESTION)
        if dlg.ShowModal() == wx.ID_YES:
            self.thread_exit()
            self.Destroy()

    def append_log(self, message, color):
        self.FileContent.AppendText(f'{message}')
        self.FileContent.SetStyle(self.len_log, self.len_log + len(message), wx.TextAttr(color, 'white'))
        self.len_log += len(message)

    def set_label(self, name, id_card_num, img):
        self.name.SetLabel(name)
        self.id_card_num.SetLabel(id_card_num)
        self.visitor_pic = wx.StaticBitmap(parent=self.panel_identity, pos=(65, 120),
                                           bitmap=img, style=wx.BORDER_SIMPLE)

    def search_oa(self, sex, id_num):
        name = self.name.GetLabel()
        self.append_log(f'{time.strftime("%Y-%m-%d %H:%M", time.localtime())}  读卡成功，开始查询访客{name}信息，', 'green')
        if id_num:
            result = get_oa_information_by_idcard(id_num)
            if result == '查询OA接口失败，请联系相关开发人员':
                self.append_log(f'{result}\n', 'red')
            else:
                try:
                    select_result = check_result_by_time(result, name)
                    if select_result in ['OA系统当前时间内未能获取该访客的信息', '审批状态未完成', '身份证姓名和OA上姓名不一致']:
                        self.append_log(f'{select_result}\n', 'red')
                        wx.MessageBox(f'{select_result}', 'Error', style=wx.ICON_ERROR)
                    elif select_result:
                        self.append_log('查询成功\n', 'green')
                        self.append_log(f'{time.strftime("%Y-%m-%d %H:%M", time.localtime())}  开始打印访客{name}的凭条',
                                        'green')
                        print_massage = print_run(name, sex, select_result)
                        if print_massage:
                            self.append_log(f'{print_massage}', 'red')
                            wx.MessageBox(print_massage, 'Error', style=wx.ICON_ERROR)
                        else:
                            self.append_log('，打印成功\n', 'green')
                            return select_result

                except Exception as e:
                    wx.MessageBox(repr(e), 'Error', style=wx.ICON_ERROR)
                else:
                    self.append_log('未能获取到身份证信息\n', 'red')
                    wx.MessageBox('未能获取到身份证信息', 'Error', style=wx.ICON_ERROR)

                return False
        return None

    def copy_name(self, event):
        name = self.name.GetLabel()
        if name != ORIGIN_NAME:
            data = wx.TextDataObject()
            data.SetText(name.strip())
            if wx.TheClipboard.Open():
                wx.TheClipboard.SetData(data)
                wx.TheClipboard.Flush()
                wx.MessageBox('姓名复制成功', 'Success', style=wx.ICON_INFORMATION)
            else:
                wx.MessageBox('无法打开系统粘贴板', 'Error', style=wx.ICON_ERROR)
        else:
            wx.MessageBox('没有找到有效的姓名', 'Error', style=wx.ICON_ERROR)

    def copy_id_card_num(self, event):
        id_card_num = self.id_card_num.GetLabel()
        if id_card_num != ORIGIN_ID_CARD_NUM:
            data = wx.TextDataObject()
            data.SetText(id_card_num.strip())
            if wx.TheClipboard.Open():
                wx.TheClipboard.SetData(data)
                wx.TheClipboard.Flush()
                wx.MessageBox('身份证号复制成功', 'Success', style=wx.ICON_INFORMATION)
            else:
                wx.MessageBox('无法打开系统粘贴板', 'Error', style=wx.ICON_ERROR)
        else:
            wx.MessageBox('没有找到有效的身份证号', 'Error', style=wx.ICON_ERROR)

    @staticmethod
    def thread_exit():
        global exit_flag
        exit_flag = True

    def on_quit(self, event):
        self.Close()

# 程序入口
if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame()
    frame.Show()
    app.MainLoop()
